// FEAT3: Finite Element Analysis Toolbox, Version 3
// Copyright (C) 2010 - 2020 by Stefan Turek & the FEAT group
// FEAT3 is released under the GNU General Public License version 3,
// see the file 'copyright.txt' in the top level directory for details.

#include <kernel/geometry/test_aux/tetris_hexa.hpp>
#include <kernel/geometry/test_aux/copy_comp_set.hpp>

namespace FEAT
{
  namespace Geometry
  {
    namespace TestAux
    {
      HexaMesh* create_tetris_mesh_3d()
      {
        Index num_entities[] =
        {
          20, // vertices
          36, // edges
          21, // quads
           4  // hexas
        };

        // create mesh
        HexaMesh* mesh = new HexaMesh(num_entities);

        // set up vertex coordinates array
        Real vtx[20*3] =
        {
           0.0, -1.0,  1.0,
           1.0, -1.0,  1.0,
          -1.0,  0.0,  1.0,
           0.0,  0.0,  1.0,
           1.0,  0.0,  1.0,
          -1.0,  1.0,  1.0,
           0.0,  1.0,  1.0,
           1.0,  1.0,  1.0,
           0.0, -1.0,  0.0,
           1.0, -1.0,  0.0,
          -1.0,  0.0,  0.0,
           0.0,  0.0,  0.0,
           1.0,  0.0,  0.0,
          -1.0,  1.0,  0.0,
           0.0,  1.0,  0.0,
           1.0,  1.0,  0.0,
           0.0, -1.0, -1.0,
           1.0, -1.0, -1.0,
           0.0,  0.0, -1.0,
           1.0,  0.0, -1.0
        };
        copy_vtx(mesh->get_vertex_set(), vtx);

        // set up vertices-at-edge
        Index v_e[36*2] =
        {
           0,  1,  //0
           0,  3,
           1,  4,
           2,  3,
           3,  4,
           2,  5,  //5
           3,  6,
           4,  7,
           5,  6,
           6,  7,
           8,  0,  //10
           9,  1,
          10,  2,
          11,  3,
          12,  4,
          13,  5,  //15
          14,  6,
          15,  7,
           8,  9,
           8, 11,
           9, 12,  //20
          10, 11,
          11, 12,
          10, 13,
          11, 14,
          12, 15,  //25
          13, 14,
          14, 15,
          16,  8,
          17,  9,
          18, 11,  //30
          19, 12,
          16, 17,
          16, 18,
          17, 19,
          18, 19,  //35
        };
        copy_idx(mesh->get_index_set<1,0>(), v_e);

        // set up vertices-at-quad
        Index v_q[21*4] =
        {
           0,  1,  3,  4,  //0
           2,  3,  5,  6,
           3,  4,  6,  7,
           8,  9,  0,  1,
           8, 11,  0,  3,
           9, 12,  1,  4,  //5
          10, 11,  2,  3,
          11, 12,  3,  4,
          10, 13,  2,  5,
          11, 14,  3,  6,
          12, 15,  4,  7,  //10
          13, 14,  5,  6,
          14, 15,  6,  7,
           8 , 9, 11, 12,
          10, 11, 13, 14,
          11, 12, 14, 15,  //15
          16, 17,  8,  9,
          16, 18,  8, 11,
          17, 19,  9, 12,
          18, 19, 11, 12,
          16, 17, 18, 19  //20
        };
        copy_idx(mesh->get_index_set<2,0>(), v_q);

        // set up edges-at-quad
        Index e_q[21*4] =
        {
           0,  4,  1,  2,
           3,  8,  5,  6,
           4,  9,  6,  7,
          18,  0, 10, 11,
          19,  1, 10, 13,
          20,  2, 11, 14,
          21,  3, 12, 13,
          22,  4, 13, 14,
          23,  5, 12, 15,
          24,  6, 13, 16,
          25,  7, 14, 17, //10
          26,  8, 15, 16,
          27,  9, 16, 17,
          18, 22, 19, 20,
          21, 26, 23, 24,
          22, 27, 24, 25,
          32, 18, 28, 29,
          33, 19, 28, 30,
          34, 20, 29, 31,
          35, 22, 30, 31,
          32, 35, 33, 34 //20
        };
        copy_idx(mesh->get_index_set<2,1>(), e_q);

        // set up vertices-at-cell
        Index v_c[4*8] =
        {
           8,  9, 11, 12,  0,  1,  3,  4,
          10, 11, 13, 14,  2,  3,  5,  6,
          11, 12, 14, 15,  3,  4,  6,  7,
          16, 17, 18, 19,  8,  9, 11, 12
        };
        copy_idx(mesh->get_index_set<3, 0>(), v_c);

        // set up edges-at-cell
        Index e_c[4*12] =
        {
          18, 22,  0,  4, 19, 20,  1,  2, 10, 11, 13, 14,
          21, 26,  3,  8, 23, 24,  5,  6, 12, 13, 15, 16,
          22, 27,  4,  9, 24, 25,  6,  7, 13, 14, 16, 17,
          32, 35, 18, 22, 33, 34, 19, 20, 28, 29, 30, 31
        };
        copy_idx(mesh->get_index_set<3,1>(), e_c);

        // set up faces-at-cell
        Index f_c[4*6] =
        {
          13,  0,  3,  7,  4,  5,
          14,  1,  6, 11,  8,  9,
          15,  2,  7, 12,  9, 10,
          20, 13, 16, 19, 17, 18
        };
        copy_idx(mesh->get_index_set<3,2>(), f_c);

        // okay
        return mesh;
      }

      void validate_refined_tetris_mesh_3d(const HexaMesh& mesh)
      {
        // validate sizes
        if(mesh.get_num_entities(0) != 81)
          throw String("Vertex count mismatch");
        if(mesh.get_num_entities(1) != 180)
          throw String("Edge count mismatch");
        if(mesh.get_num_entities(2) != 132)
          throw String("Quad count mismatch");
        if(mesh.get_num_entities(3) != 32)
          throw String("Cube count mismatch");

        // ca. 2491 indices

        // vertex coordinates array
        static const Real vtx[] =
        {
          0.0, -1.0,  1.0,
          1.0, -1.0,  1.0,
         -1.0,  0.0,  1.0,
          0.0,  0.0,  1.0,
          1.0,  0.0,  1.0,
         -1.0,  1.0,  1.0,
          0.0,  1.0,  1.0,
          1.0,  1.0,  1.0,
          0.0, -1.0,  0.0,
          1.0, -1.0,  0.0,
         -1.0,  0.0,  0.0,  //10
          0.0,  0.0,  0.0,
          1.0,  0.0,  0.0,
         -1.0,  1.0,  0.0,
          0.0,  1.0,  0.0,
          1.0,  1.0,  0.0,
          0.0, -1.0, -1.0,
          1.0, -1.0, -1.0,
          0.0,  0.0, -1.0,
          1.0,  0.0, -1.0,

          // edges
          0.5, -1.0,  1.0,  //20
          0.0, -0.5,  1.0,
          1.0, -0.5,  1.0,
         -0.5,  0.0,  1.0,
          0.5,  0.0,  1.0,
         -1.0,  0.5,  1.0,
          0.0,  0.5,  1.0,
          1.0,  0.5,  1.0,
         -0.5,  1.0,  1.0,
          0.5,  1.0,  1.0,
          0.0, -1.0,  0.5,  //30
          1.0, -1.0,  0.5,
         -1.0,  0.0,  0.5,
          0.0,  0.0,  0.5,
          1.0,  0.0,  0.5,
         -1.0,  1.0,  0.5,
          0.0,  1.0,  0.5,
          1.0,  1.0,  0.5,
          0.5, -1.0,  0.0,
          0.0, -0.5,  0.0,
          1.0, -0.5,  0.0,  //40
         -0.5,  0.0,  0.0,
          0.5,  0.0,  0.0,
         -1.0,  0.5,  0.0,
          0.0,  0.5,  0.0,
          1.0,  0.5,  0.0,
         -0.5,  1.0,  0.0,
          0.5,  1.0,  0.0,
          0.0, -1.0, -0.5,
          1.0, -1.0, -0.5,
          0.0,  0.0, -0.5, //50
          1.0,  0.0, -0.5,
          0.5, -1.0, -1.0,
          0.0, -0.5, -1.0,
          1.0, -0.5, -1.0,
          0.5,  0.0, -1.0,

          //quads
          0.5, -0.5,  1.0,
         -0.5,  0.5,  1.0,
          0.5,  0.5,  1.0,
          0.5, -1.0,  0.5,
          0.0, -0.5,  0.5, //60
          1.0, -0.5,  0.5,
         -0.5,  0.0,  0.5,
          0.5,  0.0,  0.5,
         -1.0,  0.5,  0.5,
          0.0,  0.5,  0.5,
          1.0,  0.5,  0.5,
         -0.5,  1.0,  0.5,
          0.5,  1.0,  0.5,
          0.5, -0.5,  0.0,
         -0.5,  0.5,  0.0, //70
          0.5,  0.5,  0.0,
          0.5, -1.0, -0.5,
          0.0, -0.5, -0.5,
          1.0, -0.5, -0.5,
          0.5,  0.0, -0.5,
          0.5, -0.5, -1.0,

          //cells
          0.5, -0.5,  0.5,
         -0.5,  0.5,  0.5,
          0.5,  0.5,  0.5,
          0.5, -0.5, -0.5
        };


        // vertices-at-edge array
        static const Index v_e[] =
        {
          //edges
          0, 20,
          20, 1,
          0, 21,
          21, 3,
          1, 22,
          22, 4,
          2, 23,
          23, 3,
          3, 24,
          24, 4,
          2, 25, //10
          25, 5,
          3, 26,
          26, 6,
          4, 27,
          27, 7,
          5, 28,
          28, 6,
          6, 29,
          29, 7,
          8, 30, //20
          30, 0,
          9, 31,
          31, 1,
          10, 32,
          32, 2,
          11, 33,
          33, 3,
          12, 34,
          34, 4,
          13, 35, //30
          35, 5,
          14, 36,
          36, 6,
          15, 37,
          37, 7,
          8, 38,
          38, 9,
          8, 39,
          39, 11,
          9, 40, //40
          40, 12,
          10, 41,
          41, 11,
          11, 42,
          42, 12,
          10, 43,
          43, 13,
          11, 44,
          44, 14,
          12, 45, //50
          45, 15,
          13, 46,
          46, 14,
          14, 47,
          47, 15,
          16, 48,
          48, 8,
          17, 49,
          49, 9,
          18, 50, //60
          50, 11,
          19, 51,
          51, 12,
          16, 52,
          52, 17,
          16, 53,
          53, 18,
          17, 54,
          54, 19,
          18, 55, //70
          55, 19,

          //quads
          20, 56,
          56, 24,
          21, 56,
          56, 22,
          23, 57,
          57, 28,
          25, 57,
          57, 26,
          24, 58, //80
          58, 29,
          26, 58,
          58, 27,
          38, 59,
          59, 20,
          30, 59,
          59, 31,
          39, 60,
          60, 21,
          30, 60, //90
          60, 33,
          40, 61,
          61, 22,
          31, 61,
          61, 34,
          41, 62,
          62, 23,
          32, 62,
          62, 33,
          42, 63, //100
          63, 24,
          33, 63,
          63, 34,
          43, 64,
          64, 25,
          32, 64,
          64, 35,
          44, 65,
          65, 26,
          33, 65, //110
          65, 36,
          45, 66,
          66, 27,
          34, 66,
          66, 37,
          46, 67,
          67, 28,
          35, 67,
          67, 36,
          47, 68, //120
          68, 29,
          36, 68,
          68, 37,
          38, 69,
          69, 42,
          39, 69,
          69, 40,
          41, 70,
          70, 46,
          43, 70, //130
          70, 44,
          42, 71,
          71, 47,
          44, 71,
          71, 45,
          52, 72,
          72, 38,
          48, 72,
          72, 49,
          53, 73, //140
          73, 39,
          48, 73,
          73, 50,
          54, 74,
          74, 40,
          49, 74,
          74, 51,
          55, 75,
          75, 42,
          50, 75, //150
          75, 51,
          52, 76,
          76, 55,
          53, 76,
          76, 54,

          //cubes
          69, 77,
          77, 56,
          59, 77,
          77, 63,
          60, 77, //160
          77, 61,
          70, 78,
          78, 57,
          62, 78,
          78, 67,
          64, 78,
          78, 65,
          71, 79,
          79, 58,
          63, 79, //170
          79, 68,
          65, 79,
          79, 66,
          76, 80,
          80, 69,
          72, 80,
          80, 75,
          73, 80,
          80, 74
        };

        // vertices-at-quad
        static const Index v_q[] =
        {
          0, 20, 21, 56,
          20, 1, 56, 22,
          21, 56, 3, 24,
          56, 22, 24, 4,
          2, 23, 25, 57,
          23, 3, 57, 26,
          25, 57, 5, 28,
          57, 26, 28, 6,
          3, 24, 26, 58,
          24, 4, 58, 27,
          26, 58, 6, 29, //10
          58, 27, 29, 7,
          8, 38, 30, 59,
          38, 9, 59, 31,
          30, 59, 0, 20,
          59, 31, 20, 1,
          8, 39, 30, 60,
          39, 11, 60, 33,
          30, 60, 0, 21,
          60, 33, 21, 3,
          9, 40, 31, 61, //20
          40, 12, 61, 34,
          31, 61, 1, 22,
          61, 34, 22, 4,
          10, 41, 32, 62,
          41, 11, 62, 33,
          32, 62, 2, 23,
          62, 33, 23, 3,
          11, 42, 33, 63,
          42, 12, 63, 34,
          33, 63, 3, 24, //30
          63, 34, 24, 4,
          10, 43, 32, 64,
          43, 13, 64, 35,
          32, 64, 2, 25,
          64, 35, 25, 5,
          11, 44, 33, 65,
          44, 14, 65, 36,
          33, 65, 3, 26,
          65, 36, 26, 6,
          12, 45, 34, 66, //40
          45, 15, 66, 37,
          34, 66, 4, 27,
          66, 37, 27, 7,
          13, 46, 35, 67,
          46, 14, 67, 36,
          35, 67, 5, 28,
          67, 36, 28, 6,
          14, 47, 36, 68,
          47, 15, 68, 37,
          36, 68, 6, 29, //50
          68, 37, 29, 7,
          8, 38, 39, 69,
          38, 9, 69, 40,
          39, 69, 11, 42,
          69, 40, 42, 12,
          10, 41, 43, 70,
          41, 11, 70, 44,
          43, 70, 13, 46,
          70, 44, 46, 14,
          11, 42, 44, 71, //60
          42, 12, 71, 45,
          44, 71, 14, 47,
          71, 45, 47, 15,
          16, 52, 48, 72,
          52, 17, 72, 49,
          48, 72, 8, 38,
          72, 49, 38, 9,
          16, 53, 48, 73,
          53, 18, 73, 50,
          48, 73, 8, 39, //70
          73, 50, 39, 11,
          17, 54, 49, 74,
          54, 19, 74, 51,
          49, 74, 9, 40,
          74, 51, 40, 12,
          18, 55, 50, 75,
          55, 19, 75, 51,
          50, 75, 11, 42,
          75, 51, 42, 12,
          16, 52, 53, 76, //80
          52, 17, 76, 54,
          53, 76, 18, 55,
          76, 54, 55, 19,

          //cubes
          38, 69, 59, 77,
          69, 42, 77, 63,
          59, 77, 20, 56,
          77, 63, 56, 24,
          39, 69, 60, 77,
          69, 40, 77, 61,
          60, 77, 21, 56, //90
          77, 61, 56, 22,
          30, 59, 60, 77,
          59, 31, 77, 61,
          60, 77, 33, 63,
          77, 61, 63, 34,
          41, 70, 62, 78,
          70, 46, 78, 67,
          62, 78, 23, 57,
          78, 67, 57, 28,
          43, 70, 64, 78, //100
          70, 44, 78, 65,
          64, 78, 25, 57,
          78, 65, 57, 26,
          32, 62, 64, 78,
          62, 33, 78, 65,
          64, 78, 35, 67,
          78, 65, 67, 36,
          42, 71, 63, 79,
          71, 47, 79, 68,
          63, 79, 24, 58, //110
          79, 68, 58, 29,
          44, 71, 65, 79,
          71, 45, 79, 66,
          65, 79, 26, 58,
          79, 66, 58, 27,
          33, 63, 65, 79,
          63, 34, 79, 66,
          65, 79, 36, 68,
          79, 66, 68, 37,
          52, 76, 72, 80, //120
          76, 55, 80, 75,
          72, 80, 38, 69,
          80, 75, 69, 42,
          53, 76, 73, 80,
          76, 54, 80, 74,
          73, 80, 39, 69,
          80, 74, 69, 40,
          48, 72, 73, 80,
          72, 49, 80, 74,
          73, 80, 50, 75, //130
          80, 74, 75, 51
        };

        // vertices-at-cube
        static const Index v_c[] =
        {
          8, 38, 39, 69, 30, 59, 60, 77, //0
          38, 9, 69, 40, 59, 31, 77, 61,
          39, 69, 11, 42, 60, 77, 33, 63,
          69, 40, 42, 12, 77, 61, 63, 34,
          30, 59, 60, 77, 0, 20, 21, 56,
          59, 31, 77, 61, 20, 1, 56, 22,
          60, 77, 33, 63, 21, 56, 3, 24,
          77, 61, 63, 34, 56, 22, 24, 4,
          10, 41, 43, 70, 32, 62, 64, 78,
          41, 11, 70, 44, 62, 33, 78, 65,
          43, 70, 13, 46, 64, 78, 35, 67, //10
          70, 44, 46, 14, 78, 65, 67, 36,
          32, 62, 64, 78, 2, 23, 25, 57,
          62, 33, 78, 65, 23, 3, 57, 26,
          64, 78, 35, 67, 25, 57, 5, 28,
          78, 65, 67, 36, 57, 26, 28, 6,
          11, 42, 44, 71, 33, 63, 65, 79,
          42, 12, 71, 45, 63, 34, 79, 66,
          44, 71, 14, 47, 65, 79, 36, 68,
          71, 45, 47, 15, 79, 66, 68, 37,
          33, 63, 65, 79,3, 24, 26, 58, //20
          63, 34, 79, 66, 24, 4, 58, 27,
          65, 79, 36, 68, 26, 58, 6, 29,
          79, 66, 68, 37, 58, 27, 29, 7,
          16, 52, 53, 76, 48, 72, 73, 80,
          52, 17, 76, 54, 72, 49, 80, 74,
          53, 76, 18, 55, 73, 80, 50, 75,
          76, 54, 55, 19, 80, 74, 75, 51,
          48, 72, 73, 80, 8, 38, 39, 69,
          72, 49, 80, 74,38, 9, 69, 40,
          73, 80, 50, 75, 39, 69, 11, 42, //30
          80, 74, 75, 51, 69, 40, 42, 12
        };

        // edges-at-quad
        static const Index e_q[] =
        {
          0, 74, 2, 72,
          1, 75, 72, 4,
          74, 8, 3, 73,
          75, 9, 73, 5,

          6, 78, 10, 76,
          7, 79, 76, 12,
          78, 16, 11, 77,
          79, 17, 77, 13,

          8, 82, 12, 80,
          9, 83, 80, 14,
          82, 18, 13, 81,
          83, 19, 81, 15,

          36, 86, 20, 84,
          37, 87, 84, 22,
          86, 0, 21, 85,
          87, 1, 85, 23,

          38, 90, 20, 88,
          39, 91, 88, 26,
          90, 2, 21, 89,
          91, 3, 89, 27,

          40, 94, 22, 92,
          41, 95, 92, 28,
          94, 4, 23, 93,
          95, 5, 93, 29,

          42, 98, 24, 96,
          43, 99, 96, 26,
          98, 6, 25, 97,
          99, 7, 97, 27,

          44, 102, 26, 100,
          45, 103, 100, 28,
          102, 8, 27, 101,
          103, 9, 101, 29,

          46, 106, 24, 104,
          47, 107, 104, 30,
          106, 10, 25, 105,
          107, 11, 105, 31,

          48, 110, 26, 108,
          49, 111, 108, 32,
          110, 12, 27, 109,
          111, 13, 109, 33,

          50, 114, 28, 112,
          51, 115, 112, 34,
          114, 14, 29, 113,
          115, 15, 113, 35,

          52, 118, 30, 116,
          53, 119, 116, 32,
          118, 16, 31, 117,
          119, 17, 117, 33,

          54, 122, 32, 120,
          55, 123, 120, 34,
          122, 18, 33, 121,
          123, 19, 121, 35,

          36, 126, 38, 124,
          37, 127, 124, 40,
          126, 44, 39, 125,
          127, 45, 125, 41,

          42, 130, 46, 128,
          43, 131, 128, 48,
          130, 52, 47, 129,
          131, 53, 129, 49,

          44, 134, 48, 132,
          45, 135, 132, 50,
          134, 54, 49, 133,
          135, 55, 133, 51,

          64, 138, 56, 136,
          65, 139, 136, 58,
          138, 36, 57, 137,
          139, 37, 137, 59,

          66, 142, 56, 140,
          67, 143, 140, 60,
          142, 38, 57, 141,
          143, 39, 141, 61,

          68, 146, 58, 144,
          69, 147, 144, 62,
          146, 40, 59, 145,
          147, 41, 145, 63,

          70, 150, 60, 148,
          71, 151, 148, 62,
          150, 44, 61, 149,
          151, 45, 149, 63,

          64, 154, 66, 152,
          65, 155, 152, 68,
          154, 70, 67, 153,
          155, 71, 153, 69,

          124, 158, 84, 156,
          125, 159, 156, 100,
          158, 72, 85, 157,
          159, 73, 157, 101,

          126, 160, 88, 156,
          127, 161, 156, 92,
          160, 74, 89, 157,
          161, 75, 157, 93,

          86, 160, 90, 158,
          87, 161, 158, 94,
          160, 102, 91, 159,
          161, 103, 159, 95,

          128, 164, 96, 162,
          129, 165, 162, 116,
          164, 76, 97, 163,
          165, 77, 163, 117,

          130, 166, 104, 162,
          131, 167, 162, 108,
          166, 78, 105, 163,
          167, 79, 163, 109,

          98, 166, 106, 164,
          99, 167, 164, 110,
          166, 118, 107, 165,
          167, 119, 165, 111,

          132, 170, 100, 168,
          133, 171, 168, 120,
          170, 80, 101, 169,
          171, 81, 169, 121,

          134, 172, 108, 168,
          135, 173, 168, 112,
          172, 82, 109, 169,
          173, 83, 169, 113,

          102, 172, 110, 170,
          103, 173, 170, 114,
          172, 122, 111, 171,
          173, 123, 171, 115,

          152, 176, 136, 174,
          153, 177, 174, 148,
          176, 124, 137, 175,
          177, 125, 175, 149,

          154, 178, 140, 174,
          155, 179, 174, 144,
          178, 126, 141, 175,
          179, 127, 175, 145,

          138, 178, 142, 176,
          139, 179, 176, 146,
          178, 150, 143, 177,
          179, 151, 177, 147
        };

        // edges-at-cube
        static const Index e_c[] =
        {
          36, 126, 86, 160, 38, 124, 90, 158, 20, 84, 88, 156,
          37, 127, 87, 161, 124, 40, 158, 94, 84, 22, 156, 92,
          126, 44, 160, 102, 39, 125, 91, 159, 88, 156, 26, 100,
          127, 45, 161, 103, 125, 41, 159, 95, 156, 92, 100, 28,
          86, 160, 0, 74, 90, 158, 2, 72, 21, 85, 89, 157,
          87, 161, 1, 75, 158, 94, 72, 4, 85, 23, 157, 93,
          160, 102, 74, 8,91, 159, 3, 73, 89, 157, 27, 101,
          161, 103, 75, 9, 159, 95, 73, 5, 157, 93, 101, 29,

          42, 130, 98, 166, 46, 128, 106, 164, 24, 96, 104, 162,
          43, 131, 99, 167, 128, 48, 164, 110, 96, 26, 162, 108,
          130, 52, 166, 118, 47, 129, 107, 165, 104, 162, 30, 116,
          131, 53, 167, 119, 129, 49, 165, 111, 162, 108, 116, 32,
          98, 166, 6, 78, 106, 164, 10, 76, 25, 97, 105, 163,
          99, 167, 7, 79, 164, 110, 76, 12, 97, 27, 163, 109,
          166, 118, 78, 16, 107, 165, 11, 77, 105, 163, 31, 117,
          167, 119, 79, 17, 165, 111, 77, 13, 163, 109, 117, 33,

          44, 134, 102, 172, 48, 132, 110, 170, 26, 100, 108, 168,
          45, 135, 103, 173, 132, 50, 170, 114, 100, 28, 168, 112,
          134, 54, 172, 122, 49, 133, 111, 171, 108, 168, 32, 120,
          135, 55, 173, 123, 133, 51, 171, 115, 168, 112, 120, 34,
          102, 172, 8, 82, 110, 170, 12, 80, 27, 101, 109, 169,
          103, 173, 9, 83, 170, 114, 80, 14, 101, 29, 169, 113,
          172, 122, 82, 18, 111, 171, 13, 81, 109, 169, 33, 121,
          173, 123, 83, 19, 171, 115, 81, 15, 169, 113, 121, 35,

          64, 154, 138, 178, 66, 152, 142, 176, 56, 136, 140, 174,
          65, 155, 139, 179, 152, 68, 176, 146, 136, 58, 174, 144,
          154, 70, 178, 150, 67, 153, 143, 177, 140, 174, 60, 148,
          155, 71, 179, 151, 153, 69, 177, 147, 174, 144, 148, 62,
          138, 178, 36, 126, 142, 176, 38, 124, 57, 137, 141, 175,
          139, 179, 37, 127, 176, 146, 124, 40, 137, 59, 175, 145,
          178, 150, 126, 44, 143, 177, 39, 125, 141, 175, 61, 149,
          179, 151, 127, 45, 177, 147, 125, 41, 175, 145, 149, 63
        };

        // quad-at-cube
        static const Index q_c[] =
        {
          52, 92, 12, 88, 16, 84,
          53, 93, 13, 89, 84, 20,
          54, 94, 88, 28, 17, 85,
          55, 95, 89, 29, 85, 21,
          92, 0, 14, 90, 18, 86,
          93, 1, 15, 91, 86, 22,
          94, 2, 90, 30, 19, 87,
          95, 3, 91, 31, 87, 23,

          56, 104, 24, 100, 32, 96,
          57, 105, 25, 101, 96, 36,
          58, 106, 100, 44, 33, 97,
          59, 107, 101, 45, 97, 37,
          104, 4, 26, 102, 34, 98,
          105, 5, 27, 103, 98, 38,
          106, 6, 102, 46, 35, 99,
          107, 7, 103, 47, 99, 39,

          60, 116, 28, 112, 36, 108,
          61, 117, 29, 113, 108, 40,
          62, 118, 112, 48, 37, 109,
          63, 119, 113, 49, 109, 41,
          116, 8, 30, 114, 38, 110,
          117, 9, 31, 115, 110, 42,
          118, 10, 114, 50, 39, 111,
          119, 11, 115, 51, 111, 43,

          80, 128, 64, 124, 68, 120,
          81, 129, 65, 125, 120, 72,
          82, 130, 124, 76, 69, 121,
          83, 131, 125, 77, 121, 73,
          128, 52, 66, 126, 70, 122,
          129, 53, 67, 127, 122, 74,
          130, 54, 126, 78, 71, 123,
          131, 55, 127, 79, 123, 75
        };

        // check vertex coordinates array
        if(!comp_vtx(mesh.get_vertex_set(), vtx))
          throw String("Vertex coordinate refinement failure");

        // check vertices-at-edge array
        if(!comp_idx(mesh.get_index_set<1,0>(), v_e))
          throw String("Vertex-At-Edge index set refinement failure");

        // check vertices-at-quad
        if(!comp_idx(mesh.get_index_set<2,0>(), v_q))
          throw String("Vertex-At-Quad index set refinement failure");

        // check vertices-at-cube
        if(!comp_idx(mesh.get_index_set<3,0>(), v_c))
          throw String("Vertex-At-Cube index set refinement failure");

        // check edges-at-quad
        if(!comp_idx(mesh.get_index_set<2,1>(), e_q))
          throw String("Edge-At-Quad index set refinement failure");

        // check edges-at-cube
        if(!comp_idx(mesh.get_index_set<3,1>(), e_c))
          throw String("Edge-At-Cube index set refinement failure");

        // check quad-at-cube
        if(!comp_idx(mesh.get_index_set<3,2>(), q_c))
          throw String("Quad-At-Cube index set refinement failure");

      } // validate_refined_tetris_mesh_3d

      HexaMesh* create_big_tetris_mesh_3d()
      {
        Index num_entities[] =
        {
          81, // vertices
          180, // edges
          132, // quads
          32  // hexas
        };

        // create mesh
        HexaMesh* mesh = new HexaMesh(num_entities);

        // set up vertex coordinates array
        Real vtx[81*3] =
        {
          0.0, -1.0,  1.0,
          1.0, -1.0,  1.0,
         -1.0,  0.0,  1.0,
          0.0,  0.0,  1.0,
          1.0,  0.0,  1.0,
         -1.0,  1.0,  1.0,
          0.0,  1.0,  1.0,
          1.0,  1.0,  1.0,
          0.0, -1.0,  0.0,
          1.0, -1.0,  0.0,
         -1.0,  0.0,  0.0,  //10
          0.0,  0.0,  0.0,
          1.0,  0.0,  0.0,
         -1.0,  1.0,  0.0,
          0.0,  1.0,  0.0,
          1.0,  1.0,  0.0,
          0.0, -1.0, -1.0,
          1.0, -1.0, -1.0,
          0.0,  0.0, -1.0,
          1.0,  0.0, -1.0,

          // edges
          0.5, -1.0,  1.0,  //20
          0.0, -0.5,  1.0,
          1.0, -0.5,  1.0,
         -0.5,  0.0,  1.0,
          0.5,  0.0,  1.0,
         -1.0,  0.5,  1.0,
          0.0,  0.5,  1.0,
          1.0,  0.5,  1.0,
         -0.5,  1.0,  1.0,
          0.5,  1.0,  1.0,
          0.0, -1.0,  0.5,  //30
          1.0, -1.0,  0.5,
         -1.0,  0.0,  0.5,
          0.0,  0.0,  0.5,
          1.0,  0.0,  0.5,
         -1.0,  1.0,  0.5,
          0.0,  1.0,  0.5,
          1.0,  1.0,  0.5,
          0.5, -1.0,  0.0,
          0.0, -0.5,  0.0,
          1.0, -0.5,  0.0,  //40
         -0.5,  0.0,  0.0,
          0.5,  0.0,  0.0,
         -1.0,  0.5,  0.0,
          0.0,  0.5,  0.0,
          1.0,  0.5,  0.0,
         -0.5,  1.0,  0.0,
          0.5,  1.0,  0.0,
          0.0, -1.0, -0.5,
          1.0, -1.0, -0.5,
          0.0,  0.0, -0.5, //50
          1.0,  0.0, -0.5,
          0.5, -1.0, -1.0,
          0.0, -0.5, -1.0,
          1.0, -0.5, -1.0,
          0.5,  0.0, -1.0,

          //quads
          0.5, -0.5,  1.0,
         -0.5,  0.5,  1.0,
          0.5,  0.5,  1.0,
          0.5, -1.0,  0.5,
          0.0, -0.5,  0.5, //60
          1.0, -0.5,  0.5,
         -0.5,  0.0,  0.5,
          0.5,  0.0,  0.5,
         -1.0,  0.5,  0.5,
          0.0,  0.5,  0.5,
          1.0,  0.5,  0.5,
         -0.5,  1.0,  0.5,
          0.5,  1.0,  0.5,
          0.5, -0.5,  0.0,
         -0.5,  0.5,  0.0, //70
          0.5,  0.5,  0.0,
          0.5, -1.0, -0.5,
          0.0, -0.5, -0.5,
          1.0, -0.5, -0.5,
          0.5,  0.0, -0.5,
          0.5, -0.5, -1.0,

          //cells
          0.5, -0.5,  0.5,
         -0.5,  0.5,  0.5,
          0.5,  0.5,  0.5,
          0.5, -0.5, -0.5
        };
        copy_vtx(mesh->get_vertex_set(), vtx);

        // set up vertices-at-edge
        Index v_e[180*2] =
        {
          //edges
          0, 20,
          20, 1,
          0, 21,
          21, 3,
          1, 22,
          22, 4,
          2, 23,
          23, 3,
          3, 24,
          24, 4,
          2, 25, //10
          25, 5,
          3, 26,
          26, 6,
          4, 27,
          27, 7,
          5, 28,
          28, 6,
          6, 29,
          29, 7,
          8, 30, //20
          30, 0,
          9, 31,
          31, 1,
          10, 32,
          32, 2,
          11, 33,
          33, 3,
          12, 34,
          34, 4,
          13, 35, //30
          35, 5,
          14, 36,
          36, 6,
          15, 37,
          37, 7,
          8, 38,
          38, 9,
          8, 39,
          39, 11,
          9, 40, //40
          40, 12,
          10, 41,
          41, 11,
          11, 42,
          42, 12,
          10, 43,
          43, 13,
          11, 44,
          44, 14,
          12, 45, //50
          45, 15,
          13, 46,
          46, 14,
          14, 47,
          47, 15,
          16, 48,
          48, 8,
          17, 49,
          49, 9,
          18, 50, //60
          50, 11,
          19, 51,
          51, 12,
          16, 52,
          52, 17,
          16, 53,
          53, 18,
          17, 54,
          54, 19,
          18, 55, //70
          55, 19,

          //quads
          20, 56,
          56, 24,
          21, 56,
          56, 22,
          23, 57,
          57, 28,
          25, 57,
          57, 26,
          24, 58, //80
          58, 29,
          26, 58,
          58, 27,
          38, 59,
          59, 20,
          30, 59,
          59, 31,
          39, 60,
          60, 21,
          30, 60, //90
          60, 33,
          40, 61,
          61, 22,
          31, 61,
          61, 34,
          41, 62,
          62, 23,
          32, 62,
          62, 33,
          42, 63, //100
          63, 24,
          33, 63,
          63, 34,
          43, 64,
          64, 25,
          32, 64,
          64, 35,
          44, 65,
          65, 26,
          33, 65, //110
          65, 36,
          45, 66,
          66, 27,
          34, 66,
          66, 37,
          46, 67,
          67, 28,
          35, 67,
          67, 36,
          47, 68, //120
          68, 29,
          36, 68,
          68, 37,
          38, 69,
          69, 42,
          39, 69,
          69, 40,
          41, 70,
          70, 46,
          43, 70, //130
          70, 44,
          42, 71,
          71, 47,
          44, 71,
          71, 45,
          52, 72,
          72, 38,
          48, 72,
          72, 49,
          53, 73, //140
          73, 39,
          48, 73,
          73, 50,
          54, 74,
          74, 40,
          49, 74,
          74, 51,
          55, 75,
          75, 42,
          50, 75, //150
          75, 51,
          52, 76,
          76, 55,
          53, 76,
          76, 54,

          //cubes
          69, 77,
          77, 56,
          59, 77,
          77, 63,
          60, 77, //160
          77, 61,
          70, 78,
          78, 57,
          62, 78,
          78, 67,
          64, 78,
          78, 65,
          71, 79,
          79, 58,
          63, 79, //170
          79, 68,
          65, 79,
          79, 66,
          76, 80,
          80, 69,
          72, 80,
          80, 75,
          73, 80,
          80, 74
        };
        copy_idx(mesh->get_index_set<1,0>(), v_e);

        // set up vertices-at-quad
        Index v_q[132*4] =
        {
          0, 20, 21, 56,
          20, 1, 56, 22,
          21, 56, 3, 24,
          56, 22, 24, 4,
          2, 23, 25, 57,
          23, 3, 57, 26,
          25, 57, 5, 28,
          57, 26, 28, 6,
          3, 24, 26, 58,
          24, 4, 58, 27,
          26, 58, 6, 29, //10
          58, 27, 29, 7,
          8, 38, 30, 59,
          38, 9, 59, 31,
          30, 59, 0, 20,
          59, 31, 20, 1,
          8, 39, 30, 60,
          39, 11, 60, 33,
          30, 60, 0, 21,
          60, 33, 21, 3,
          9, 40, 31, 61, //20
          40, 12, 61, 34,
          31, 61, 1, 22,
          61, 34, 22, 4,
          10, 41, 32, 62,
          41, 11, 62, 33,
          32, 62, 2, 23,
          62, 33, 23, 3,
          11, 42, 33, 63,
          42, 12, 63, 34,
          33, 63, 3, 24, //30
          63, 34, 24, 4,
          10, 43, 32, 64,
          43, 13, 64, 35,
          32, 64, 2, 25,
          64, 35, 25, 5,
          11, 44, 33, 65,
          44, 14, 65, 36,
          33, 65, 3, 26,
          65, 36, 26, 6,
          12, 45, 34, 66, //40
          45, 15, 66, 37,
          34, 66, 4, 27,
          66, 37, 27, 7,
          13, 46, 35, 67,
          46, 14, 67, 36,
          35, 67, 5, 28,
          67, 36, 28, 6,
          14, 47, 36, 68,
          47, 15, 68, 37,
          36, 68, 6, 29, //50
          68, 37, 29, 7,
          8, 38, 39, 69,
          38, 9, 69, 40,
          39, 69, 11, 42,
          69, 40, 42, 12,
          10, 41, 43, 70,
          41, 11, 70, 44,
          43, 70, 13, 46,
          70, 44, 46, 14,
          11, 42, 44, 71, //60
          42, 12, 71, 45,
          44, 71, 14, 47,
          71, 45, 47, 15,
          16, 52, 48, 72,
          52, 17, 72, 49,
          48, 72, 8, 38,
          72, 49, 38, 9,
          16, 53, 48, 73,
          53, 18, 73, 50,
          48, 73, 8, 39, //70
          73, 50, 39, 11,
          17, 54, 49, 74,
          54, 19, 74, 51,
          49, 74, 9, 40,
          74, 51, 40, 12,
          18, 55, 50, 75,
          55, 19, 75, 51,
          50, 75, 11, 42,
          75, 51, 42, 12,
          16, 52, 53, 76, //80
          52, 17, 76, 54,
          53, 76, 18, 55,
          76, 54, 55, 19,

          //cubes
          38, 69, 59, 77,
          69, 42, 77, 63,
          59, 77, 20, 56,
          77, 63, 56, 24,
          39, 69, 60, 77,
          69, 40, 77, 61,
          60, 77, 21, 56, //90
          77, 61, 56, 22,
          30, 59, 60, 77,
          59, 31, 77, 61,
          60, 77, 33, 63,
          77, 61, 63, 34,
          41, 70, 62, 78,
          70, 46, 78, 67,
          62, 78, 23, 57,
          78, 67, 57, 28,
          43, 70, 64, 78, //100
          70, 44, 78, 65,
          64, 78, 25, 57,
          78, 65, 57, 26,
          32, 62, 64, 78,
          62, 33, 78, 65,
          64, 78, 35, 67,
          78, 65, 67, 36,
          42, 71, 63, 79,
          71, 47, 79, 68,
          63, 79, 24, 58, //110
          79, 68, 58, 29,
          44, 71, 65, 79,
          71, 45, 79, 66,
          65, 79, 26, 58,
          79, 66, 58, 27,
          33, 63, 65, 79,
          63, 34, 79, 66,
          65, 79, 36, 68,
          79, 66, 68, 37,
          52, 76, 72, 80, //120
          76, 55, 80, 75,
          72, 80, 38, 69,
          80, 75, 69, 42,
          53, 76, 73, 80,
          76, 54, 80, 74,
          73, 80, 39, 69,
          80, 74, 69, 40,
          48, 72, 73, 80,
          72, 49, 80, 74,
          73, 80, 50, 75, //130
          80, 74, 75, 51
        };
        copy_idx(mesh->get_index_set<2,0>(), v_q);

        // set up vertices-at-cell
        Index v_c[32*8] =
        {
          8, 38, 39, 69, 30, 59, 60, 77, //0
          38, 9, 69, 40, 59, 31, 77, 61,
          39, 69, 11, 42, 60, 77, 33, 63,
          69, 40, 42, 12, 77, 61, 63, 34,
          30, 59, 60, 77, 0, 20, 21, 56,
          59, 31, 77, 61, 20, 1, 56, 22,
          60, 77, 33, 63, 21, 56, 3, 24,
          77, 61, 63, 34, 56, 22, 24, 4,
          10, 41, 43, 70, 32, 62, 64, 78,
          41, 11, 70, 44, 62, 33, 78, 65,
          43, 70, 13, 46, 64, 78, 35, 67, //10
          70, 44, 46, 14, 78, 65, 67, 36,
          32, 62, 64, 78, 2, 23, 25, 57,
          62, 33, 78, 65, 23, 3, 57, 26,
          64, 78, 35, 67, 25, 57, 5, 28,
          78, 65, 67, 36, 57, 26, 28, 6,
          11, 42, 44, 71, 33, 63, 65, 79,
          42, 12, 71, 45, 63, 34, 79, 66,
          44, 71, 14, 47, 65, 79, 36, 68,
          71, 45, 47, 15, 79, 66, 68, 37,
          33, 63, 65, 79,3, 24, 26, 58, //20
          63, 34, 79, 66, 24, 4, 58, 27,
          65, 79, 36, 68, 26, 58, 6, 29,
          79, 66, 68, 37, 58, 27, 29, 7,
          16, 52, 53, 76, 48, 72, 73, 80,
          52, 17, 76, 54, 72, 49, 80, 74,
          53, 76, 18, 55, 73, 80, 50, 75,
          76, 54, 55, 19, 80, 74, 75, 51,
          48, 72, 73, 80, 8, 38, 39, 69,
          72, 49, 80, 74,38, 9, 69, 40,
          73, 80, 50, 75, 39, 69, 11, 42, //30
          80, 74, 75, 51, 69, 40, 42, 12
        };
        copy_idx(mesh->get_index_set<3, 0>(), v_c);

        // okay
        return mesh;
      }

      HexaSubMesh* create_tetris_quad_submesh_3d()
      {

       /* Creates the 3D tetris quad submesh.

                                    14
                                   /|
                                  / |
                                 P  |
                                /   X
                               /    |
                              6     |
                              |     |
                              |----11---------V--------12
                              |    /|                  /|
                              F   / |                 / |
                              |  M  |                N  |
                              | /   S               /   T
                              |/    |              /    |
                              3---------D---------4     |
                                    |                   |
                                    8---------R---------9
          y
          ^
          |
          |
         11---->x
         /
       z/
       v
      */

        Index num_entities[] =
        {
          8, // vertices
          10, // edges
          3,  // quads
          0 // hexas
        };

        // create mesh
        HexaSubMesh* mesh = new HexaSubMesh(num_entities, true);
        // create a AttributeSet that holds one value for each vertex
        HexaSubMesh::AttributeSetType* my_attrib_set = new HexaSubMesh::AttributeSetType(num_entities[0],2);
        // Add the attribute to mesh
        mesh->add_attribute(my_attrib_set, "HexaSubAttributeSet");

        // set up vertex coordinates array
        Real attr[] =
        {
          0.0, 0.0,
          1.0, 1.0,
          2.0, 2.0,
          1.0, 2.0,
          2.0, 1.0,
          2.0, 0.0,
          1.0, 0.0,
          0.0, 1.0
        };
        copy_attr(*(mesh->find_attribute("HexaSubAttributeSet")), attr);

        // set up vertices-at-edge array
        Index v_e[] =
        {
          6, 0,
          5, 6,
          7, 1,
          1, 4,
          0, 7,
          6, 1,
          4, 5,
          3, 1,
          2, 4,
          3, 2
        };
        copy_idx(mesh->get_index_set<1,0>(), v_e);

        // set up vertices-at-quad array
        Index v_q[] =
        {
          0, 6, 7, 1,
          5, 4, 6, 1,
          3, 2, 1, 4
        };
        copy_idx(mesh->get_index_set<2,0>(), v_q);

        // set up edges-at-quad array
        Index e_q[] =
        {
          0, 2, 4, 5,
          6, 5, 1, 3,
          9, 3, 7, 8
        };
        copy_idx(mesh->get_index_set<2,1>(), e_q);

        // set up vertex-target indices
        Index vti[] =
        {
          6, 11, 9, 8, 12, 4, 3, 14
        };
        copy_trg(mesh->get_target_set<0>(), vti);

        // set up edge-target indices
        Index eqi[] =
        {
          6, 4, 24, 22, 16, 13, 14, 19, 20, 18
        };
        copy_trg(mesh->get_target_set<1>(), eqi);

        // set up quad-target indices
        Index qti[] =
        {
          9, 7, 13
        };
        copy_trg(mesh->get_target_set<2>(), qti);
        // okay
        return mesh;
      } // create_tetris_quad_submesh_3d()

      void validate_refined_tetris_quad_submesh_3d(const HexaSubMesh& mesh)
      {
        // validate sizes
        if(mesh.get_num_entities(0) != 21)
          throw String("Vertex count mismatch");
        if(mesh.get_num_entities(1) != 32)
          throw String("Edge count mismatch");
        if(mesh.get_num_entities(2) != 12)
          throw String("Quad count mismatch");

        // check vertex coordinates array
        Real attr[] =
        {
          0.0, 0.0,
          1.0, 1.0,
          2.0, 2.0,
          1.0, 2.0,
          2.0, 1.0,
          2.0, 0.0,
          1.0, 0.0,
          0.0, 1.0,

          0.5, 0.0,
          1.5, 0.0,
          0.5, 1.0,
          1.5, 1.0,
          0.0, 0.5,
          1.0, 0.5,
          2.0, 0.5,
          1.0, 1.5,
          2.0, 1.5,
          1.5, 2.0,
          0.5, 0.5,
          1.5, 0.5,
          1.5, 1.5
        };
        if(!comp_attr(*(mesh.find_attribute("HexaSubAttributeSet")), attr))
          throw String("Attribute refinement failure");

        // check vertices-at-edge array
        Index v_e[] =
        {
          6, 8,
          8, 0,
          5, 9,
          9, 6,
          7, 10,
          10, 1,
          1, 11,
          11, 4,
          0, 12,
          12, 7,
          6, 13,
          13, 1,
          4, 14,
          14, 5,
          3, 15,
          15, 1,
          2, 16,
          16, 4,
          3, 17,
          17, 2,
          8, 18,
          18, 10,
          12, 18,
          18, 13,
          14, 19,
          19, 13,
          9, 19,
          19, 11,
          17, 20,
          20, 11,
          15, 20,
          20, 16
        };
        if(!comp_idx(mesh.get_index_set<1,0>(), v_e))
          throw String("Vertex-At-Edge index set refinement failure");

        // check vertices-at-quad
        Index v_q[] =
        {
          0, 8, 12, 18,
          8, 6, 18, 13,
          12, 18, 7, 10,
          18, 13, 10, 1,
          5, 14, 9, 19,
          14, 4, 19, 11,
          9, 19, 6, 13,
          19, 11, 13, 1,
          3, 17, 15, 20,
          17, 2, 20, 16,
          15, 20, 1, 11,
          20, 16, 11, 4
        };
        if(!comp_idx(mesh.get_index_set<2,0>(), v_q))
          throw String("Vertex-At-Quad index set refinement failure");

        // check edges-at-quad
        Index e_q[] =
        {
          1, 22, 8, 20,
          0, 23, 20, 10,
          22, 4, 9, 21,
          23, 5, 21, 11,
          13, 26, 2, 24,
          12, 27, 24, 7,
          26, 10, 3, 25,
          27, 11, 25, 6,
          18, 30, 14, 28,
          19, 31, 28, 16,
          30, 6, 15, 29,
          31, 7, 29, 17
        };
        if(!comp_idx(mesh.get_index_set<2,1>(), e_q))
          throw String("Edges-At-Quad refinement failure");

        // check vertex-target indices
        Index vti[] =
        {
          6, 11, 9, 8, 12, 4, 3, 14,
          26, 24, 44, 42, 36, 33, 34,
          39, 40, 38, 65, 63, 69
        };
        if(!comp_trg(mesh.get_target_set<0>(), vti))
          throw String("Vertex-Target-Indices refinement failure");

        // check edge-target indices
        Index eti[] =
        {
          12, 13, 9, 8, 49, 48, 44, 45,
          33, 32, 27, 26, 28, 29, 38, 39,
          40, 41, 36, 37, 109, 108, 111, 110,
          103, 102, 101, 100, 124, 125, 126, 127
        };
        if(!comp_trg(mesh.get_target_set<1>(), eti))
          throw String("Edge-Target-Indices refinement failure");

        // check quad-target indices
        Index qti[] =
        {
          39, 38, 37, 36,
          31, 29, 30, 28,
          52, 53, 54, 55
        };
        if(!comp_trg(mesh.get_target_set<2>(), qti))
          throw String("Quad-Target-Indices refinement failure");
      } //validate_refined_tetris_quad_submesh_3d

    } // namespace TestAux
  } // namespace Geometry
} // namespace FEAT
